/**
 * 大日历表格
 * Created by wjxu on 2018/6/14
 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import CalandarTd from './CalendarTd';
import './Datepicker.less';
import './style.less';

function getData(currDate, data) {
  const date = moment(currDate, 'YYYYMMDD');
  const days = date.daysInMonth();
  const currYear = date.year();
  const currMonth = date.month();
  const firstDayOfWeek = moment(date).startOf('month').weekday();
  const list = [];
  for (let i = firstDayOfWeek, startDay = moment(date).startOf('month'); i > 0; i--) {
    // 上一个月的占位日期
    // const startDay = date.startOf('month');
    // 注意：使用 subtract 方法，将会变更 startDay 本身，即每次减一天
    const duration = moment.duration({ days: 1 });
    list.unshift({
      date: startDay.subtract(duration).format('YYYYMMDD'),
      isThisMonth: false,
    });
  }
  for (let i = 1; i <= days; i++) {
    const dateStr = moment([currYear, currMonth, i]).format('YYYYMMDD');
    list.push({
      date: dateStr,
      detail: data[dateStr],
      isThisMonth: true,
    });
  }
  // 下一个月的占位日期
  const lastMonthPlaceholder = list.length % 7 !== 0 ? 7 - (list.length % 7) : 0;
  for (let i = 1, endDay = moment(date).endOf('month'); i <= lastMonthPlaceholder; i++) {
    // const endDay = date.endOf('month');
    // 注意：使用 add 方法，正整数将不会会变更 endDay 本身，负数会变跟 endDay 本省
    const duration = moment.duration({ days: 1 });
    list.push({
      date: endDay.add(duration).format('YYYYMMDD'),
      isThisMonth: false,
    });
  }
  return list;
}

class CalendarTable extends Component {
  constructor(props) {
    super(props);
    this.state = {
      calendarData: getData(this.props.currDate, this.props.data),
    };
  }

  componentWillReceiveProps(nextProps) {
    if (moment(nextProps.currDate, 'YYYYMMDD').format('YYYYMM') === moment(this.props.currDate, 'YYYYMMDD').format('YYYYMM')) {
      return false;
    }
    // 更新状态值
    this.setState({
      calendarData: getData(nextProps.currDate, nextProps.data),
    });
    return true;
  }

  getTd(dayData) {
    const { date, isThisMonth } = dayData;
    const { customTd, handleTd, ...rest } = this.props;

    const tdStyle = !isThisMonth ? 'calendar-other-month' : '';

    return (
      <CalandarTd key={date} customTd={customTd} date={date} className={tdStyle} {...rest}>
        { typeof handleTd === 'function' && handleTd(dayData) }
      </CalandarTd>
    );
  }

  getTr(weekData) {
    return weekData.map(e => this.getTd(e));
  }

  setCalendar() {
    const d = this.state.calendarData;
    const trs = [];
    for (let i = 0, week = 1, len = d.length; i < len; i += 7, week++) {
      const weekData = d.slice(i, i + 7);

      trs.push(<tr key={`week${week}`} >{ this.getTr(weekData) }</tr>);
    }
    return <tbody>{ trs }</tbody>;
  }

  render() {
    return (
      <table className="table table-striped table-bordered table-condensed calendar-table">
        <caption>{ this.props.currDate.format('YYYY-MM') }</caption>
        <thead>
          <tr>
            <th>星期日</th>
            <th>星期一</th>
            <th>星期二</th>
            <th>星期三</th>
            <th>星期四</th>
            <th>星期五</th>
            <th>星期六</th>
          </tr>
        </thead>
        { this.setCalendar() }
      </table>
    );
  }
}

CalendarTable.defaultProps = {
  currDate: moment(),
  customTd: false,
  data: {},
  handleTd: null,
  endDate: '',
};

CalendarTable.propTypes = {
  currDate: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(moment),
  ]),
  customTd: PropTypes.bool,
  data: PropTypes.object,
  handleTd: PropTypes.func,
  endDate: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(moment),
  ]),
};

export default CalendarTable;
